#include "Handlers.h"
#include "Settings.h"
#include "CMSInterface.h"
#include "StorageInterface.h"

ACE_THR_FUNC_RETURN ReactorThread(void *arg) {

    ACE_Reactor *reactor = (ACE_Reactor *) arg;
    reactor->run_reactor_event_loop();

    return 0;
}

bool CheckController()
{
	const int sleep_time = Settings::GetSettings()->JOB_CHECK_DELAY*3; 
	const int check_time = sleep_time * 5; 

	int p_t , s_t;

	while(true)
	{
		if(_DB_SUCCESS == DBInterface::GetControllerTimeElapsed(Settings::GetSettings()->RENDERER_ID , p_t , s_t))
		{
			if(Settings::GetSettings()->IsPrimary())
			{
				if(p_t > s_t && s_t <= check_time)
				{

				}
				else
				{
					printf("this is primary\n");
					DBInterface::SetControllerTime(Settings::GetSettings()->RENDERER_ID , true); 
					break;
				}
			}
			else
			{
				if( p_t <= s_t && p_t <= check_time)
				{

				}
				else
				{
					printf("this is secondary\n");
					DBInterface::SetControllerTime(Settings::GetSettings()->RENDERER_ID , false); 
					break;
				}
			}

		}
		else
		{
			return false;
		}


		printf("other controller is running .. wait .. \n");
		sleep(sleep_time);
	}

	return true;

}

int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{

	ACE_Process_Mutex mu(CONTROLLER_NAME);
	if( mu.tryacquire() != 0)
	{
		printf("You can't load multiple controllers in one machine!\n");
		return -1;
	}

	if(!Settings::Start())
	{
		return -1;
	}


	LOG::Start(); 

	if(Settings::GetSettings()->LOCAL_ADDR.length() == 0)
	{
		printf("[controller] can not get local addr\n");
		return -1;
	}

	if(!Settings::GetSettings()->IsControllerAddr())
	{
		printf("[controller] Invalid controller for this zone\n");
		return -1;
	}


	printf("\n############################ First Setting Values ########################\n");
	printf("%s" , Settings::GetSettings()->dump().c_str());
	printf("\n##########################################################################\n");
	printf("LOCAL ADDR : %s\n" , Settings::GetSettings()->LOCAL_ADDR.c_str());

	if(!CheckController())
		return -1;

	printf("###############################################################################\n");

	
	DBInterface::ResetMonitorData(Settings::GetSettings()->RENDERER_ID);

	while(!CMSInterface::CancelAll())
	{
		sleep(1);
	}

	LOG::PushProcessLog(_REQUIRED , Settings::GetSettings()->IsPrimary() ? "PRIMARY START" : "SECONDARY START");
	printf("[Controller] started\n");


	SettingCheckThread setting_ct;
	setting_ct.activate();

	GetJobThread jt;
	jt.activate();

	PROCESS cp;
	cp.activate();



    ACE_TP_Reactor tpReactor;
    ACE_Reactor reactor(&tpReactor);
	ACE_Thread_Manager::instance()->spawn_n((int)ACE_OS::num_processors() * 5, ReactorThread, &reactor);


    AcceptHandler *acceptHandler = 0;
    ACE_NEW_NORETURN (acceptHandler, AcceptHandler(&reactor));

    if (acceptHandler == 0)
	{
      ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%N:%l: Failed to allocate ")
                        ACE_TEXT ("accept handler. (errno = %i: %m)\n"), ACE_ERRNO_GET), -1);
	}

    if (acceptHandler->open() == -1) 
	{
        delete acceptHandler;
        ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%N:%l: Failed to open accept ")
                          ACE_TEXT ("handler. Exiting.\n")), -1);
    }

    ACE_Reactor::instance ()->run_reactor_event_loop ();

	DBInterface::ResetMonitorData(Settings::GetSettings()->RENDERER_ID);

	LOG::PushProcessLog(_REQUIRED , "END");
	printf("[Controller] terminated\n");


	Settings::Release();
	DBInterface::DeleteAllConnections();

	exit(0);


	return 0;

}